﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace BakalarskaPraca.Forms
{
    public partial class DrawingForm : Form
    {
        private Point _startPoint;
        private Bitmap _currentDataBuffer;
        private Bitmap _overDrawingLayer;
        private Graphics _overDrawingLayerGraphics;
        private Graphics _currentDataBufferGraphics;
        private Color _selectedColor;
        private Bitmap _colorGallery;

        private enum DrawingStyle
        {
            Brush, Ellipse, Rectangle
        }

        private DrawingStyle _selectedTool;
        
        public DrawingForm()
        {
            InitializeComponent();
            this._currentDataBuffer = new Bitmap(this.DrawPB.Width, this.DrawPB.Height);
            this._overDrawingLayer = new Bitmap(this.DrawPB.Width, this.DrawPB.Height);
            this._overDrawingLayerGraphics = Graphics.FromImage(this._overDrawingLayer);
            this._currentDataBufferGraphics = Graphics.FromImage(this._currentDataBuffer);
            this._currentDataBufferGraphics.Clear(Color.White);
            this._overDrawingLayerGraphics.Clear(Color.Transparent);
            this.SelectColor(-1);
            this._selectedTool = DrawingStyle.Brush;
        }

        private void DrawPbMouseDown(object sender, MouseEventArgs e)
        {
            this._startPoint = e.Location;
            this.Draw(e.Location);
        }

        private void DrawPbMouseMove(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                this.Draw(e.Location);
            }
        }

        private void DrawPbMouseUp(object sender, MouseEventArgs e)
        {
            this._currentDataBufferGraphics.DrawImage(this._overDrawingLayer, 0, 0);
            this._overDrawingLayerGraphics.Clear(Color.Transparent);
            this.ShowBuffers();
        }

        private void ShowBuffers()
        {
            this.DrawPB.BackgroundImage = this._currentDataBuffer;
            this.DrawPB.Image = this._overDrawingLayer;
        }

        private Brush GetBrush(int x, int y, int size, Color color)
        {
            GraphicsPath path = new GraphicsPath();
            path.AddEllipse(x, y, size, size);
            PathGradientBrush brush = new PathGradientBrush(path);
            brush.WrapMode = WrapMode.Clamp;
            brush.SurroundColors = new Color[] { Color.Transparent };
            brush.CenterColor = color;
            path.Dispose();
            return brush;
        }

        private void ColorPbResize(object sender, EventArgs e)
        {
            this.SelectColor(-1);
        }

        private void SelectColor(int x)
        {
            Bitmap colorGallery = new Bitmap(this.ColorPB.Width, this.ColorPB.Height);
            Graphics g = Graphics.FromImage(colorGallery);
            float scale = this.ColorPB.Width / 255f;
            for (int i = 0; i < 255; i++)
            {
                Brush b = new SolidBrush(Color.FromArgb(i, i, i));
                g.FillRectangle(b, i * scale, 0, (i + 1) * scale, this.ColorPB.Height);
            }
            this._colorGallery = colorGallery;
            if (x < 0)
            {
                this._selectedColor = Color.Black;
            } 
            else if (x >= this.ColorPB.Width)
            {
                this._selectedColor = Color.White;
            } 
            else 
            {
                this._selectedColor = this._colorGallery.GetPixel(x, 0);
            }
            g.DrawLine(Pens.GreenYellow, x, 0, x, this.ColorPB.Width);
            this.ColorPB.Image = colorGallery;
        }

        private void ColorPbSelectColor(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                this.SelectColor(e.X);
            }
        }

        private void ProceedBtnClick(object sender, EventArgs e)
        {
            this.DialogResult = DialogResult.OK;
        }

        private void BrushSelectCheckedChanged(object sender, EventArgs e)
        {
            this._selectedTool = DrawingStyle.Brush;
        }

        private void Draw(Point location)
        {
            Brush brush = new SolidBrush(this._selectedColor);
            switch (_selectedTool)
            {
                case DrawingStyle.Brush:
                    int size = this.BrushSizeTrackBar.Value;
                    int x = location.X - size / 2;
                    int y = location.Y - size / 2;
                    brush = this.GetBrush(x, y, size, this._selectedColor);
                    this._overDrawingLayerGraphics.FillEllipse(brush, x, y, size, size);
                    break;
                case DrawingStyle.Ellipse:
                    this._overDrawingLayerGraphics.Clear(Color.Transparent);
                    this._overDrawingLayerGraphics.FillEllipse(brush, this._startPoint.X, this._startPoint.Y, location.X - this._startPoint.X, location.Y - this._startPoint.Y);
                    break;
                case DrawingStyle.Rectangle:
                    this._overDrawingLayerGraphics.Clear(Color.Transparent);
                    this._overDrawingLayerGraphics.FillRectangle(brush, this._startPoint.X, this._startPoint.Y, location.X - this._startPoint.X, location.Y - this._startPoint.Y);
                    break;
                default:
                    throw new ArgumentOutOfRangeException();
            }
            this.ShowBuffers();
        }

        private void EllipseSelectCheckedChanged(object sender, EventArgs e)
        {
            this._selectedTool = DrawingStyle.Ellipse;
        }

        private void RectangleSelectCheckedChanged(object sender, EventArgs e)
        {
            this._selectedTool = DrawingStyle.Rectangle;
        }

        private void ClearBtnClick(object sender, EventArgs e)
        {
            this._currentDataBufferGraphics.Clear(Color.White);
            this.ShowBuffers();
        }
    }
}
